import 'dart:async';

import 'package:flutter/cupertino.dart';
import 'package:flutter/services.dart';
import 'package:kq_flutter_widgets/theme/kq_theme_manager.dart';
import 'package:kq_flutter_widgets/utils/permission_util.dart';
import 'package:permission_handler/permission_handler.dart';

import '../../resources/l10n/kq_intl.dart';

/// 扫码调用原生工具类
class ScanNativeUtil {
  static const _methodChannelName = 'flutter.keqiang.com/scan';

  static final _platformMethod = const MethodChannel(_methodChannelName)
    ..setMethodCallHandler(_methodCallHandler);

  ScanNativeUtil._inner();

  static final Map<String, VoidCallback> _onTapHelpMap = {};

  static Future<dynamic> _methodCallHandler(MethodCall call) async {
    switch (call.method) {
      case 'onTapHelp':
        if (call.arguments is String) {
          _onTapHelpMap[call.arguments]?.call();
        }
        break;
    }
  }

  static List<int>? _mapScanType(
    List<ScanType>? scanTypes,
  ) {
    List<int>? types;
    if (scanTypes != null && scanTypes.isNotEmpty) {
      types = [];
      for (var value in scanTypes) {
        types.add(value.code);
      }
    }
    return types;
  }

  /// 扫码
  ///
  /// [appBarColor]为导航条颜色
  ///
  /// [title] 标题
  ///
  /// [hint] 提示文字
  ///
  /// [useAlbum] 是否开启相册选图
  ///
  /// [scanTypes] 支持的扫码类型，不传则支持所有格式
  ///
  /// [imgScanFailedBack] 扫描图片失败，是否退出扫码界面回调失败结果
  ///
  /// [applyScanPermissionHint]扫码申请相机权限说明。[permanentlyDeniedScanPermissionHint]相机权限被永久拒绝提示。
  ///
  /// [applyAlbumPermissionHint]访问相册权限说明，android版本>=33时，申请的为读取媒体资料权限。否则为读取磁盘权限。
  /// [permanentlyDeniedAlbumPermissionHint]磁盘权限被永久拒绝提示。
  ///
  /// [onTapHelp]表示点击帮助按钮回调,设置此值则展示帮助按钮。[cancelLabel]为识别图片二维码错误时，弹窗取消按钮的文本。
  /// [seeHelpLabel]为识别图片二维码错误时，弹窗确认按钮的文本。[cancelLabel]和[seeHelpLabel]仅[onTapHelp]不为null时有效。
  static void scanWithCallback({
    int? appBarColor,
    String? title,
    String? hint,
    bool useAlbum = false,
    bool imgScanFailedBack = false,
    String? imgScanFailedHint,
    List<ScanType>? scanTypes,
    bool turnOnLight = false,
    bool showLightButton = false,
    String? applyScanPermissionHint,
    String? applyAlbumPermissionHint,
    String? permanentlyDeniedScanPermissionHint,
    String? permanentlyDeniedAlbumPermissionHint,
    VoidCallback? onTapHelp,
    String? cancelLabel,
    String? seeHelpLabel,
    required Function(ScanResult result) callback,
  }) {
    scan(
      appBarColor: appBarColor,
      title: title,
      hint: hint,
      useAlbum: useAlbum,
      scanTypes: scanTypes,
      turnOnLight: turnOnLight,
      showLightButton: showLightButton,
      applyScanPermissionHint: applyScanPermissionHint,
      applyAlbumPermissionHint: applyAlbumPermissionHint,
      permanentlyDeniedScanPermissionHint: permanentlyDeniedScanPermissionHint,
      permanentlyDeniedAlbumPermissionHint:
          permanentlyDeniedAlbumPermissionHint,
      onTapHelp: onTapHelp,
      cancelLabel: cancelLabel,
      seeHelpLabel: seeHelpLabel,
    ).then((value) => callback(value));
  }

  /// 扫码
  ///
  /// [appBarColor]为导航条颜色
  ///
  /// [title] 标题
  ///
  /// [hint] 提示文字
  ///
  /// [useAlbum] 是否开启相册选图
  ///
  /// [scanTypes] 支持的扫码类型，不传则支持所有格式
  ///
  /// [imgScanFailedBack] 扫描图片失败，是否退出扫码界面回调失败结果
  ///
  /// [turnOnLight] 是否打开闪光灯
  ///
  /// [showLightButton] 是否展示控制闪光灯按钮
  ///
  /// [applyScanPermissionHint]扫码申请相机权限说明。[permanentlyDeniedScanPermissionHint]相机权限被永久拒绝提示。
  ///
  /// [applyAlbumPermissionHint]访问相册权限说明，android版本>=33时，申请的为读取媒体资料权限。否则为读取磁盘权限。
  /// [permanentlyDeniedAlbumPermissionHint]磁盘权限被永久拒绝提示。
  ///
  /// [onTapHelp]表示点击帮助按钮回调,设置此值则展示帮助按钮。[cancelLabel]为识别图片二维码错误时，弹窗取消按钮的文本。
  /// [seeHelpLabel]为识别图片二维码错误时，弹窗确认按钮的文本。[cancelLabel]和[seeHelpLabel]仅[onTapHelp]不为null时有效。
  static Future<ScanResult> scan({
    int? appBarColor,
    String? title,
    String? hint,
    bool useAlbum = false,
    bool imgScanFailedBack = false,
    String? imgScanFailedHint,
    List<ScanType>? scanTypes,
    bool turnOnLight = false,
    bool showLightButton = false,
    String? applyScanPermissionHint,
    String? applyAlbumPermissionHint,
    String? permanentlyDeniedScanPermissionHint,
    String? permanentlyDeniedAlbumPermissionHint,
    VoidCallback? onTapHelp,
    String? cancelLabel,
    String? seeHelpLabel,
  }) async {
    var status = await PermissionUtils.request(
      Permission.camera,
      applyTitle: KqIntl.currentResource.applyPermissionTitle,
      applyDesc: applyScanPermissionHint,
      permanentlyDeniedDesc: permanentlyDeniedScanPermissionHint,
    );

    if (status != PermissionStatus.granted) {
      return const ScanResult(isCancel: true);
    }

    String? tag;
    try {
      var args = {
        'title': title,
        'hint': hint,
        'useAlbum': useAlbum,
        'imgScanFailedBack': imgScanFailedBack,
        'imgScanFailedHint': imgScanFailedHint,
        "scanTypes": _mapScanType(scanTypes),
        "navColor":
            appBarColor ?? KqThemeManager.getCommonConfig().mainColor?.value,
        'turnOnLight': turnOnLight,
        'showLightButton': showLightButton,
        'applyAlbumPermissionHint': applyAlbumPermissionHint,
        'permanentlyDeniedAlbumPermissionHint':
            permanentlyDeniedAlbumPermissionHint
      };

      if (onTapHelp != null) {
        tag = DateTime.now().millisecondsSinceEpoch.toString();
        _onTapHelpMap[tag] = onTapHelp;
        args['onTapHelpTag'] = tag;
        args['cancelLabel'] = cancelLabel;
        args['seeHelpLabel'] = seeHelpLabel;
      }

      var result = await _platformMethod.invokeMethod('startScan', args);
      int? code = result['code'];
      if (tag != null) {
        _onTapHelpMap.remove(tag);
      }
      return ScanResult(
          isCancel: code != 0 && code != 1,
          content: code == 1 ? result['data'] ?? "" : null,
          errorMsg: code == 0 ? result['msg'] ?? "" : null);
    } on PlatformException catch (e) {
      if (tag != null) {
        _onTapHelpMap.remove(tag);
      }
      debugPrint(e.message);
      return ScanResult(errorMsg: e.message);
    } catch (e) {
      if (tag != null) {
        _onTapHelpMap.remove(tag);
      }
      debugPrint(e.toString());
      return ScanResult(errorMsg: e.toString());
    }
  }
}

/// 支持的扫码格式
enum ScanType {
  ///二维码
  qrCode(0),

  /// 一维码
  bar(1);

  final int code;

  const ScanType(this.code);
}

/// 扫码结果
class ScanResult {
  const ScanResult({this.content, this.errorMsg, this.isCancel = false});

  /// 扫码内容,此值为null则表示扫码失败或扫码被取消
  final String? content;

  /// 扫码异常信息，此值不为null时表示扫码失败
  final String? errorMsg;

  /// 用户是否取消扫码
  final bool isCancel;
}
